#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
flake8 插件
用于 Python 代码风格和质量检查
"""

import os
import subprocess
import json
from typing import Dict, List, Any


class Flake8Plugin:
    """flake8 插件"""
    
    def __init__(self):
        self.name = "flake8"
        self.description = "Python 代码风格和质量检查"
    
    def execute(self, config: Dict[str, Any], context: Dict[str, Any]) -> Dict[str, Any]:
        """执行 flake8 检查"""
        try:
            # 检查是否有 Python 文件
            python_files = self._find_python_files(config.get('paths', ['.']))
            if not python_files:
                return {
                    'success': True,
                    'output': '未找到 Python 文件，跳过 flake8 检查',
                    'exit_code': 0
                }
            
            # 检查 flake8 是否安装
            if not self._check_flake8_installed():
                return {
                    'success': False,
                    'output': 'flake8 未安装，请运行: pip install flake8',
                    'exit_code': 1
                }
            
            # 获取配置参数
            max_line_length = config.get('max_line_length', 88)
            ignore_errors = config.get('ignore', [])
            select_errors = config.get('select', [])
            exclude_paths = config.get('exclude', [])
            config_file = config.get('config_file', None)
            
            # 构建命令
            cmd = ['flake8']
            
            # 添加最大行长度
            cmd.extend(['--max-line-length', str(max_line_length)])
            
            # 添加忽略的错误
            if ignore_errors:
                cmd.extend(['--ignore', ','.join(ignore_errors)])
            
            # 添加选择的错误
            if select_errors:
                cmd.extend(['--select', ','.join(select_errors)])
            
            # 添加排除路径
            if exclude_paths:
                cmd.extend(['--exclude', ','.join(exclude_paths)])
            
            # 添加配置文件
            if config_file and os.path.exists(config_file):
                cmd.extend(['--config', config_file])
            
            # 添加输出格式
            cmd.extend(['--format', '%(path)s:%(row)d:%(col)d: %(code)s %(text)s'])
            
            # 添加要检查的路径
            paths = config.get('paths', ['.'])
            cmd.extend(paths)
            
            # 执行命令
            result = subprocess.run(
                cmd,
                capture_output=True,
                text=True,
                timeout=300
            )
            
            # 解析结果
            output_lines = result.stdout.split('\n') if result.stdout else []
            error_lines = result.stderr.split('\n') if result.stderr else []
            
            # 统计错误
            errors = []
            warnings = []
            
            for line in output_lines:
                if line.strip():
                    if any(code in line for code in ['E9', 'F63', 'F7', 'F82']):
                        errors.append(line)
                    else:
                        warnings.append(line)
            
            # 生成报告
            total_issues = len(errors) + len(warnings)
            
            if result.returncode == 0:
                return {
                    'success': True,
                    'output': f'flake8 检查通过，无问题发现',
                    'exit_code': 0,
                    'details': {
                        'total_issues': 0,
                        'errors': 0,
                        'warnings': 0
                    }
                }
            else:
                output = f"flake8 检查发现 {total_issues} 个问题：\n"
                output += f"- 错误: {len(errors)}\n"
                output += f"- 警告: {len(warnings)}\n\n"
                
                if errors:
                    output += "错误详情:\n"
                    for error in errors[:10]:  # 只显示前10个错误
                        output += f"  {error}\n"
                    if len(errors) > 10:
                        output += f"  ... 还有 {len(errors) - 10} 个错误\n"
                    output += "\n"
                
                if warnings:
                    output += "警告详情:\n"
                    for warning in warnings[:5]:  # 只显示前5个警告
                        output += f"  {warning}\n"
                    if len(warnings) > 5:
                        output += f"  ... 还有 {len(warnings) - 5} 个警告\n"
                
                return {
                    'success': False,
                    'output': output,
                    'exit_code': result.returncode,
                    'details': {
                        'total_issues': total_issues,
                        'errors': len(errors),
                        'warnings': len(warnings),
                        'error_list': errors,
                        'warning_list': warnings
                    }
                }
                
        except subprocess.TimeoutExpired:
            return {
                'success': False,
                'output': 'flake8 检查超时',
                'exit_code': 124
            }
        except Exception as e:
            return {
                'success': False,
                'output': f'flake8 检查失败: {str(e)}',
                'exit_code': 1
            }
    
    def _find_python_files(self, paths: List[str]) -> List[str]:
        """查找 Python 文件"""
        python_files = []
        
        for path in paths:
            if os.path.isfile(path) and path.endswith('.py'):
                python_files.append(path)
            elif os.path.isdir(path):
                for root, dirs, files in os.walk(path):
                    # 跳过常见的忽略目录
                    dirs[:] = [d for d in dirs if d not in ['.git', '__pycache__', '.pytest_cache', 'venv', '.venv']]
                    
                    for file in files:
                        if file.endswith('.py'):
                            python_files.append(os.path.join(root, file))
        
        return python_files
    
    def _check_flake8_installed(self) -> bool:
        """检查 flake8 是否安装"""
        try:
            subprocess.run(['flake8', '--version'], capture_output=True, check=True)
            return True
        except (subprocess.CalledProcessError, FileNotFoundError):
            return False


def execute(config: Dict[str, Any], context: Dict[str, Any]) -> Dict[str, Any]:
    """插件入口函数"""
    plugin = Flake8Plugin()
    return plugin.execute(config, context)
